# file ignore
"""
用户核心模型
包含:
1. UserModel - 用户基础信息
2. UserProfileModel - 用户详细资料
3. OrganizationModel - 组织架构
"""

from datetime import datetime
from decimal import Decimal
from typing import Optional

import bcrypt
from tortoise import fields

from app.core.constants import BoolEnum, GenderType, OrgTypeEnum
from app.models.base_model import BaseModel


class UserModel(BaseModel):
    """用户基础信息"""

    username = fields.CharField(max_length=32, unique=True, description="用户名")

    is_active = fields.IntEnumField(BoolEnum, default=BoolEnum.TRUE.value, description="是否激活")
    is_staff = fields.IntEnumField(BoolEnum, default=BoolEnum.FALSE.value, description="是否为员工")
    is_superuser = fields.IntEnumField(BoolEnum, default=BoolEnum.FALSE.value, description="是否为超级用户")
    date_joined = fields.DatetimeField(auto_now_add=True)

    balance = fields.DecimalField(max_digits=10, decimal_places=2, null=True, default=Decimal("0.00"))
    points = fields.IntField(default=0, description="积分")

    # Relation field
    roles = fields.ManyToManyField("models.UserRoleModel", related_name="users", through="auth_user2role")
    # reverse relation
    profile: fields.ReverseRelation["UserProfileModel"]
    orgs: fields.ReverseRelation["OrganizationModel"]
    point_records: fields.ReverseRelation["UserPointRecordModel"]  # type: ignore
    balance_records: fields.ReverseRelation["UserBalanceRecordModel"]  # type: ignore
    auth_accounts: fields.ReverseRelation["UserAuthAccountModel"]  # type: ignore

    class Meta:
        table = "auth_user"

    async def get_auth_account(self, provider: "AuthProviderEnum") -> Optional["UserAuthAccountModel"]:  # type: ignore
        """获取用户某个认证源的主账号"""
        return await self.auth_accounts.filter(provider=provider, is_primary=BoolEnum.TRUE.value).first()

    @property
    async def last_login(self) -> Optional[datetime]:
        """获取最后登录时间"""
        account = await self.auth_accounts.order_by("-last_used").first()
        return account.last_used if account else None


class UserProfileModel(BaseModel):
    """用户详细资料"""

    user = fields.ForeignKeyField("models.UserModel", related_name="profile", null=False)
    nickname = fields.CharField(max_length=255, null=True, description="昵称")
    avatar = fields.CharField(max_length=255, null=True, description="头像")
    gender = fields.IntEnumField(GenderType, default=GenderType.NO.value, description="性别")
    birthday = fields.DateField(null=True, description="出生年月")
    introduction = fields.CharField(max_length=200, null=True, description="个人介绍")

    class Meta:
        table = "auth_user_profile"

    @property
    def full_name(self) -> str:
        """获取用户全名"""
        return f"{self.nickname or ''}"


class OrganizationModel(BaseModel):
    """组织架构"""

    name = fields.CharField(max_length=255, description="机构名称")
    parent = fields.ForeignKeyField(
        "models.OrganizationModel",
        related_name="children",
        null=True,
    )
    sort = fields.IntField(default=0, description="排序")
    org_type = fields.IntEnumField(OrgTypeEnum, default=OrgTypeEnum.COMPANY, description="组织架构类型")
    is_show = fields.IntField(default=BoolEnum.TRUE.value, description="是否在菜单中显示")

    users = fields.ManyToManyField("models.UserModel", related_name="orgs", through="auth_organization2user")

    class Meta:
        table = "auth_organization"
